package j.util.web;

import j.framework.core.LoginUser;
import j.data.ActionMessage;
import j.data.ActionResult;
import j.util.*;
import j.util.exception.ApplicationException;
import j.util.jdbc.simple.annotation.Column;
import j.util.jdbc.simple.annotation.DataType;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Time;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * User: jason
 * Date: 13-4-22 下午2:53
 */
public class HttpView implements Serializable {
    public static final String DEFAULT_CHARSET = "UTF-8";
    public static final String DEFAULT_CONTENT_TYPE = "text/html; charset=utf-8";
    public static final String PLAIN_CONTENT_TYPE = "text/plain; charset=utf-8";
    public static final String JSON_RESULT_TAG_KEY = "hasErrors";
    public static final String JSON_MESSAGE_TAG_KEY = "message";
    public static final String JSON_DATA_TAG_KEY = "data";

    private static final Pattern GET_ONLY_DATE_PART_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}");
    public static final int SEARCH_DATE_PARAMETER_BEGIN_FLAG = 1;
    public static final int SEARCH_DATE_PARAMETER_END_FLAG = 2;

    private HttpServletRequest request;
    private HttpServletResponse response;

    private Map<String,String> parameters = New.map();



    public Map<String,String> getMap(){
        Map<String,String> map = New.map();
        map.putAll(parameters);
        map.remove("act");
        return map;
    }

    private boolean neededToClearToken = false;

    public HttpView(HttpServletRequest request,HttpServletResponse response,boolean neededToClearToken){
        this.request = request;
        this.response = response;
        Map<String,String[]> map =  request.getParameterMap();
        if(null!=map && map.size()>0){
            for(Map.Entry<String,String[]> entry : map.entrySet()){
                parameters.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
            }
        }
        /**
         * 将本次请求中的所有参数以key为p增加到request请求中,以使原先的参数能够恢复到界面中
         */
        this.request.setAttribute("p",parameters);
        this.neededToClearToken = neededToClearToken;
    }

    public HttpServletRequest getRequest(){
        return request;
    }
    public HttpServletResponse getResponse(){
        return response;
    }

    /**
     * jsp页面直接给出,不用写扩展名,路径基于/WEB-INF/jsp/
     */
    public void forward(String jspPage){
        String s = "/WEB-INF/jsp/" + jspPage + ".jsp";
        try {
            request.getRequestDispatcher(s).forward(request,response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void forward1(String jspPage){
        try {
            request.getRequestDispatcher(jspPage).forward(request,response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void redirect(String url) throws IOException {
        response.sendRedirect(url);
    }

    /**
     * 以utf-8编码输出到客户端,同时contentType默认为text/html;charset=utf-8
     * @param s 需要输出到客户端的内容
     * @throws java.io.IOException
     */
    public void toOut(String s) throws IOException{
        response.setCharacterEncoding(DEFAULT_CHARSET);
        response.setContentType(DEFAULT_CONTENT_TYPE);
        PrintWriter out = response.getWriter();
        out.print(s);
        out.flush();
    }

    public static void toOut(HttpServletRequest request,HttpServletResponse response,String outS) throws IOException{
        response.setCharacterEncoding(DEFAULT_CHARSET);
        response.setContentType(DEFAULT_CONTENT_TYPE);
        PrintWriter out = response.getWriter();
        out.print(outS);
        out.flush();
    }

    public void toValidJson(String json) throws IOException{
        if(StringUtils.isNotEmpty(json)){
            toOut(String.format("{%s:false,%s:%s}",JSON_RESULT_TAG_KEY,JSON_DATA_TAG_KEY,json));
        }else{
            toOut(String.format("{%s:false}",JSON_RESULT_TAG_KEY));
        }
    }

    public void toEasyUiGrid(int total,List<?> list)throws IOException{
        String json;
        if(list==null||list.size()==0){
            json = String.format("{\"total\":%s,\"rows\":%s}",0,"[]");
        }else{
            json = String.format("{\"total\":%s,\"rows\":%s}", total, j.util.json.JsonUtils.toJson(list));
        }
        toOut(json);
    }
    public void toEasyUiGrid(int total,List<?> list,List<Map<String,Object>> footers)throws IOException{
        String json;
        if(list==null||list.size()==0){
            if(footers==null||footers.size()==0){
                json = String.format("{\"total\":%s,\"rows\":%s}",0,"[]");
            }else{
                json = String.format("{\"total\":%s,\"rows\":%s,\"footer\":%s}",0,"[]",j.util.json.JsonUtils.toJson(footers));
            }
        }else{
            if(footers!=null && footers.size()>0){
                json = String.format("{\"total\":%s,\"rows\":%s,\"footer\":%s}",
                        total, j.util.json.JsonUtils.toJson(list), j.util.json.JsonUtils.toJson(footers));
            }else{
                json = String.format("{\"total\":%s,\"rows\":%s}", total, j.util.json.JsonUtils.toJson(list));
            }
        }
        toOut(json);
    }
    public void toEasyUiGrid(int total,List<?> list,Map<String,Object> footer)throws IOException{
        List<Map<String,Object>> footers = New.list();
        if(footer != null){
            footers.add(footer);
        }
        toEasyUiGrid(total, list,footers);
    }

    public void toText(String text) throws IOException{
        response.setCharacterEncoding(DEFAULT_CHARSET);
        response.setContentType(PLAIN_CONTENT_TYPE);
        PrintWriter out = response.getWriter();
        out.print(text);
        out.flush();
    }

    public void toClient(ActionResult ar)throws IOException{
        toClient(ar,null);
    }

    public void toClient(ActionResult ar,String data) throws IOException{
        String outS;
        if(hasErrors(ar)){
            StringBuilder s = new StringBuilder("[");
            List<ActionMessage> actionMessages = ar.toList();
            for(ActionMessage msg : actionMessages){
                if(StringUtils.isNotEmpty(msg.getKey())){
                    s.append(String.format("{key:\"%s\",msg:\"%s\"},",msg.getKey(),msg.getMessage()));
                }else{
                    s.append(String.format("{msg:\"%s\"},",msg.getMessage()));
                }
            }
            s.deleteCharAt(s.length()-1);
            s.append("]");
            outS = String.format("{%s:true,%s:%s}",JSON_RESULT_TAG_KEY,JSON_MESSAGE_TAG_KEY,s.toString());
        }else{
            if(StringUtils.isNotEmpty(data)){
                outS = String.format("{%s:false,%s:\"%s\"}",JSON_RESULT_TAG_KEY,JSON_DATA_TAG_KEY,data);
            }else{
                outS = String.format("{%s:false}",JSON_RESULT_TAG_KEY);
            }
        }
        toOut(outS);
    }

    public static void toClient(HttpServletRequest request,HttpServletResponse response,ActionResult ar,String data,boolean neededToClearToken) throws IOException{
        boolean hasErrors = ar.hasErrors(request);
        String outS;
        if(hasErrors){
            StringBuilder s = new StringBuilder("[");
            List<ActionMessage> actionMessages = ar.toList();
            for(ActionMessage msg : actionMessages){
                if(StringUtils.isNotEmpty(msg.getKey())){
                    s.append(String.format("{key:\"%s\",msg:\"%s\"},",msg.getKey(),msg.getMessage()));
                }else{
                    s.append(String.format("{msg:\"%s\"},",msg.getMessage()));
                }
            }
            s.deleteCharAt(s.length()-1);
            s.append("]");
            outS = String.format("{%s:true,%s:%s}",JSON_RESULT_TAG_KEY,JSON_MESSAGE_TAG_KEY,s.toString());
        }else{
            if(neededToClearToken){
                ResubmitUtils.clearToken(request);//清空令牌
            }
            if(StringUtils.isNotEmpty(data)){
                outS = String.format("{%s:false,%s:\"%s\"}",JSON_RESULT_TAG_KEY,JSON_DATA_TAG_KEY,data);
            }else{
                outS = String.format("{%s:false}",JSON_RESULT_TAG_KEY);
            }
        }
        toOut(request,response,outS);
    }

    /**
     * 向客户端输入javascript脚本,若ar中有错误,则将错误信息封装在ul中,若没有错误,则直接输入script中指定的脚本
     * @param ar
     * @param script
     * @throws java.io.IOException
     */
    public void toClient1(ActionResult ar,String script)throws IOException{
        String scripts;
        if(hasErrors(ar)){
            //有错误,生成错误列表
            /*List<ActionMessage> errs = ar.toList();
            StringBuilder s = new StringBuilder("<ul>");
            for(ActionMessage e : errs){
                s.append("<li>").append(e.getMessage()).append("</li>");
            }
            s.append("</ul>");*/
            List<ActionMessage> errs = ar.toList();
            StringBuilder s = new StringBuilder();
            int i=1;
            for(ActionMessage e : errs){
                s.append(i++).append(".").append(e.getMessage()).append("\\n");
            }
            scripts = String.format("<script>parent.f.setError(\"%s\");</script>",s.toString());
        }else{
            String _script = StringUtils.isNotEmpty(script)?script:"";
            scripts = String.format("<script>parent.f.close();%s</script>",_script);
        }
        toOut(scripts);
    }
    public void toResult(ActionResult ar,String script)throws IOException{
        String scripts;
        if(hasErrors(ar)){
            //有错误,生成错误列表
            /*List<ActionMessage> errs = ar.toList();
            StringBuilder s = new StringBuilder("<ul>");
            for(ActionMessage e : errs){
                s.append("<li>").append(e.getMessage()).append("</li>");
            }
            s.append("</ul>");*/
            List<ActionMessage> errs = ar.toList();
            StringBuilder s = new StringBuilder();
            s.append("<ol>");
            for(ActionMessage e : errs){
                s.append("<li>").append(e.getMessage()).append("</li>");
            }
            s.append("</ol>");
            scripts = String.format("<script>parent.f.setError(\"%s\");</script>",s.toString().replaceAll("\\s",""));
        }else{
            String _script = StringUtils.isNotEmpty(script)?script:"";
            scripts = String.format("<script>parent.f.close();%s</script>",_script);
        }
        toOut(scripts);
    }
    public void toResult(ActionResult ar)throws IOException{
        toResult(ar,null);
    }


    /**
     * 判断ActionResult中是否有错,若正确,则清理防重复提交的令牌,若有错,直接返回错误标志即可
     * @param ar
     * @return
     */
    public boolean hasErrors(final ActionResult ar){
        boolean hasErrors = ar.hasErrors(request);
        if(!hasErrors && neededToClearToken){
            ResubmitUtils.clearToken(request);//清空令牌
        }
        return hasErrors;
    }

    public void toClient2(ActionResult ar,String script)throws IOException{
        String scripts;
        if(hasErrors(ar)){
            //有错误,生成错误列表
            List<ActionMessage> errs = ar.toList();
            StringBuilder s = new StringBuilder("<ul>");
            for(ActionMessage e : errs){
                s.append("<li>").append(e.getMessage()).append("</li>");
            }
            s.append("</ul>");
            scripts = String.format("<script>parent.setError(\"%s\");</script>",s.toString());
        }else{
            String _script = StringUtils.isNotEmpty(script)?script:"";
            scripts = String.format("<script>%s</script>",_script);
        }
        toOut(scripts);
    }

    /**
     * 将错误信息输出到客户端,格式:{hasErrors:true,message:'msg'}
     * @param errorMessage 错误消息
     * @throws java.io.IOException
     */
    public void toError(String errorMessage) throws IOException {
        //以json格式返回
        toOut(String.format("{%s:true,%s:\"%s\"}",JSON_RESULT_TAG_KEY,JSON_MESSAGE_TAG_KEY,errorMessage));
    }

    /**
     * 获取经DES加密的原字符串
     * @param key
     * @return
     */
    public String getId(String key,String optKey){
        String s = request.getParameter(key);
        if(StringUtils.isNotEmpty(s)){
            String cryptKey = DesSessionKey.getDesCryptKey(request, optKey);
            if(StringUtils.isNullOrEmpty(cryptKey)){
                throw new ApplicationException("无法在用户会话中获取DES密钥,请重新登录.");
            }
            s = DES.decrypt(s, cryptKey);
            if(StringUtils.isNullOrEmpty(s)){
                throw new ApplicationException("无法将key为[%s]转换为正确的ID值,请重试!",key);
            }
        }else{
            return null;
        }
        return s;
    }

    /**
     * 获取经DES加密的原字符串
     * @param key
     * @return
     */
    public String getId(String key){
        return getId(key, null);
    }

    public String getDesId(String key){
        String data = getParameter(key);
        if(StringUtils.isNotEmpty(data)){
            return DES.decrypt(data);
        }
        return "";
    }

    public String getParameter(String key){
        return parameters.get(key);
    }

    public int getIntParamter(String key){
        return getIntParamter(key,0);
    }
    public int getIntParamter(String key,int defaultInt){
        return ConvertUtils.toInt(parameters.get(key), defaultInt);
    }
    public Float getFloatParameter(String key){
        String s = getParameter(key);
        if(StringUtils.isNullOrEmpty(s)){
            return null;
        }
        return ConvertUtils.toSingle(s);
    }
    public boolean getBooleanParameter(String key){
        String v = getParameter(key);
        if(StringUtils.isNotEmpty(v)){
            v = v.toLowerCase();
            if(v.equals("true")
                    || v.equals("1")
                    || v.equals("yes")
                    || v.equals("on")){
                return true;
            }
        }
        return false;
    }

    /**
     * 获取日期参数,默认format为:yyyy-MM-dd
     * @param key
     * @return
     */
    public Date getDateParameter(String key){
        String v = getParameter(key);
        if(StringUtils.isNotEmpty(v)){
            return DateUtils.toDate(v, "yyyy-MM-dd");
        }
        return null;
    }

    /**
     * 主要针对查询日期时间段的参数,需要在flag参数中指定是日期段的哪个,即开始日期还是结束日期
     * 若为开始日期,则将日期参数格式化为:yyyy-MM-dd 00:00:00
     * 若为结束日期,则将日期参数格式化为:yyyy-MM-dd 23:59:59
     * @param key
     * @param flag
     * @return
     */
    public Date getDateParameter(String key,int flag){
        String v = getParameter(key);
        if(StringUtils.isNotEmpty(v)){
            Matcher m = GET_ONLY_DATE_PART_PATTERN.matcher(v);
            if(m.find()){
                v = m.group();
                if(flag == SEARCH_DATE_PARAMETER_BEGIN_FLAG){
                    v += " 00:00:00";
                }else if(flag == SEARCH_DATE_PARAMETER_END_FLAG){
                    v += " 23:59:59.999";
                }
                return DateUtils.toDate(v, "yyyy-MM-dd HH:mm:ss.sss");
            }
        }
        return null;
    }
    /**
     * 获取日期时间参数,默认format为:yyyy-MM-dd HH:mm:ss
     * @param key
     * @return
     */
    public Date getDateTimeParameter(String key){
        String v = getParameter(key);
        if(StringUtils.isNotEmpty(v)){
            return DateUtils.toDate(v, "yyyy-MM-dd HH:mm:ss");
        }
        return null;
    }

    public Object getAttribute(String attributeName){
        return request.getAttribute(attributeName);
    }

    public String getStringAttribute(String attributeName){
        return (String)getAttribute(attributeName);
    }

    public void setAttribute(String attributeName,Object attributeValue){
        request.setAttribute(attributeName, attributeValue);
    }

    public void forward(String jspPage, ActionResult ar,String okMessage) {
        if(ar.isOk(request) && StringUtils.isNotEmpty(okMessage)){
            request.setAttribute(ActionResult.REQUEST_OK_MESSAGE_ATTRIBUTE_NAME,okMessage);
        }
        forward(jspPage);
    }

    public <T> T getBean(Class<T> clazz,final ActionResult ar){
        T bean = null;
        try{
            bean = clazz.newInstance();
        }catch(Exception e){
            throw new RuntimeException(String.format("实体类%s不存在。", clazz.getName()));
        }
        Object v;
        String setMethodName,displayName,parameterValue,str;

        Column $column;
        Field[] fields = clazz.getDeclaredFields();
        DataType dataType;
        int i;
        double d;
        float fl;
        long l;
        short s;
        boolean needDes = false;
        for(Field f : fields){
            //把值从请求中取出来
            //如果请求中不存在此参数，则直接忽略
            if(!request.getParameterMap().containsKey(f.getName())){
                continue;
            }
            needDes = false;
            parameterValue = ParamUtils.getParameterValues(request, f.getName());
            displayName = f.getName();
            $column = f.getAnnotation(Column.class);
            v = null;
            if($column!=null){
                if($column.needDes()){
                    v = parameterValue;
                    needDes = true;
                }else {
                    //按给定的值进行验证数字的正确性
                    displayName = $column.displayName();
                    if (StringUtils.isNullOrEmpty(displayName)) {
                        displayName = f.getName();
                    }
                    //在给定的参数值不为空时检测数据类型是否有误
                    if (StringUtils.isNotEmpty(parameterValue)) {
                        v = parseBeanValue(f, parameterValue, displayName, ar);
                    }
                    //检测值的必填项
                    if (!$column.nullable()) {
                        //要求此字段必须有值
                        if (StringUtils.isNullOrEmpty(parameterValue)) {
                            ar.add(String.format("请输入[%s]项！", displayName));
                            continue;
                        }
                    }
                    //检测值的取值范围
                    if ($column.min() > Integer.MIN_VALUE && v != null) {
                        //用户指定了最小值
                        if (v instanceof String) {
                            str = (String) v;
                            if (str.length() < $column.min()) {
                                ar.add(String.format("[%s]的长度必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Integer) {
                            i = (Integer) v;
                            if (i < $column.min()) {
                                ar.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Float) {
                            fl = (Float) v;
                            if (fl < $column.min()) {
                                ar.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Double) {
                            d = (Double) v;
                            if (d < $column.min()) {
                                ar.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Long) {
                            l = (Long) v;
                            if (l < $column.min()) {
                                ar.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Short) {
                            s = (Short) v;
                            if (s < $column.min()) {
                                ar.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        }
                    }
                    if ($column.max() < Integer.MAX_VALUE && v != null) {
                        //用户指定了最大值
                        if (v instanceof String) {
                            str = (String) v;
                            if (str.length() > $column.max()) {
                                ar.add(String.format("[%s]的长度必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Integer) {
                            i = (Integer) v;
                            if (i > $column.max()) {
                                ar.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Float) {
                            fl = (Float) v;
                            if (fl > $column.max()) {
                                ar.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Double) {
                            d = (Double) v;
                            if (d > $column.max()) {
                                ar.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Long) {
                            l = (Long) v;
                            if (l > $column.max()) {
                                ar.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Short) {
                            s = (Short) v;
                            if (s > $column.max()) {
                                ar.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        }
                    }
                    if(StringUtils.isNotEmpty(parameterValue)) {
                        //只有在不为空时，才验证这些数据类型是否正确
                        dataType = $column.datatype();
                        if (dataType.equals(DataType.EMAIL)) {
                            ar.isValidEmail(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电子邮件格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.MOBILE)) {
                            ar.isValidMobile(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的手机格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.TELEPHONE)) {
                            ar.isValidTelephone(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电话格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.PHONE)) {
                            ar.isValidPhone(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电话格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.URL)) {
                            ar.isValidURL(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的网址格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.ZipCode)) {
                            ar.isValidZip(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的邮政编码，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.CHINESE)) {
                            ar.isValidChinese(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的中文字符，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.IDCARD)) {
                            ar.isValidIdentityCard(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的身份证号，请重新输入！", displayName));
                        }
                    }
                }
            }else{
                v = parseBeanValue(f,parameterValue,displayName,ar);
            }
            if(v!=null){
                setMethodName = "set"+Character.toUpperCase(f.getName().charAt(0))+f.getName().substring(1);
                try {
                    Method m = clazz.getDeclaredMethod(setMethodName,f.getType());
                    if(needDes){
                        v = DES.decrypt((String) v);
                    }
                    m.invoke(bean,v);
                } catch (Exception e) {
                    ar.add(String.format("[%s]的值输入有错，请输入正确的类型！",displayName));
                }
            }
        }
        return bean;
    }

    public static JMap loadRequestParams(HttpServletRequest request){
        JMap map = New.jmap();
        Map<String,String[]> _m = request.getParameterMap();
        for(Map.Entry<String,String[]> entry : _m.entrySet()){
            if(entry.getValue().length==1){
                map.put(entry.getKey(),entry.getValue()[0]);
            }else{
                map.put(entry.getKey(),StringUtils.join(entry.getValue(),","));
            }
        }
        return map;
    }

    public static  <T> T getBean(JMap params,Class<T> clazz,ActionResult actionResult){
        T bean = null;
        try{
            bean = clazz.newInstance();
        }catch(Exception e){
            throw new RuntimeException(String.format("实体类%s不存在。", clazz.getName()));
        }
        Object v;
        String setMethodName,displayName,parameterValue,str;

        Column $column;
        Field[] fields = clazz.getDeclaredFields();
        DataType dataType;
        int i;
        double d;
        float fl;
        long l;
        short s;
        boolean needDes = false;
        for(Field f : fields){
            //把值从请求中取出来
            //如果请求中不存在此参数，则直接忽略
            if(!params.containsKey(f.getName())){
                continue;
            }
            needDes = false;
            parameterValue = params.getString(f.getName());
            displayName = f.getName();
            $column = f.getAnnotation(Column.class);
            v = null;
            if($column!=null){
                if($column.needDes()){
                    v = parameterValue;
                    needDes = true;
                }else {
                    //按给定的值进行验证数字的正确性
                    displayName = $column.displayName();
                    if (StringUtils.isNullOrEmpty(displayName)) {
                        displayName = f.getName();
                    }
                    //在给定的参数值不为空时检测数据类型是否有误
                    if (StringUtils.isNotEmpty(parameterValue)) {
                        v = parseBeanValue(f,parameterValue,displayName,actionResult);
                    }
                    //检测值的必填项
                    if (!$column.nullable()) {
                        //要求此字段必须有值
                        if (StringUtils.isNullOrEmpty(parameterValue)) {
                            actionResult.add(String.format("请输入[%s]项！", displayName));
                            continue;
                        }
                    }
                    //检测值的取值范围
                    if ($column.min() > Integer.MIN_VALUE && v != null) {
                        //用户指定了最小值
                        if (v instanceof String) {
                            str = (String) v;
                            if (str.length() < $column.min()) {
                                actionResult.add(String.format("[%s]的长度必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Integer) {
                            i = (Integer) v;
                            if (i < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Float) {
                            fl = (Float) v;
                            if (fl < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Double) {
                            d = (Double) v;
                            if (d < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Long) {
                            l = (Long) v;
                            if (l < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        } else if (v instanceof Short) {
                            s = (Short) v;
                            if (s < $column.min()) {
                                actionResult.add(String.format("[%s]的值必须大于等于%s!", displayName, $column.min()));
                                continue;
                            }
                        }
                    }
                    if ($column.max() < Integer.MAX_VALUE && v != null) {
                        //用户指定了最大值
                        if (v instanceof String) {
                            str = (String) v;
                            if (str.length() > $column.max()) {
                                actionResult.add(String.format("[%s]的长度必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Integer) {
                            i = (Integer) v;
                            if (i > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Float) {
                            fl = (Float) v;
                            if (fl > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Double) {
                            d = (Double) v;
                            if (d > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Long) {
                            l = (Long) v;
                            if (l > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        } else if (v instanceof Short) {
                            s = (Short) v;
                            if (s > $column.max()) {
                                actionResult.add(String.format("[%s]的值必须小于等于%s!", displayName, $column.max()));
                                continue;
                            }
                        }
                    }
                    if(StringUtils.isNotEmpty(parameterValue)) {
                        //只有在不为空时，才验证这些数据类型是否正确
                        dataType = $column.datatype();
                        if (dataType.equals(DataType.EMAIL)) {
                            actionResult.isValidEmail(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电子邮件格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.MOBILE)) {
                            actionResult.isValidMobile(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的手机格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.TELEPHONE)) {
                            actionResult.isValidTelephone(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电话格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.PHONE)) {
                            actionResult.isValidPhone(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的电话格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.URL)) {
                            actionResult.isValidURL(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的网址格式，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.ZipCode)) {
                            actionResult.isValidZip(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的邮政编码，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.CHINESE)) {
                            actionResult.isValidChinese(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的中文字符，请重新输入！", displayName));
                        } else if (dataType.equals(DataType.IDCARD)) {
                            actionResult.isValidIdentityCard(f.getName(), parameterValue,
                                    String.format("[%s]不是有效的身份证号，请重新输入！", displayName));
                        }
                    }
                }
            }else{
                v = parseBeanValue(f,parameterValue,displayName,actionResult);
            }
            if(v!=null){
                setMethodName = "set"+Character.toUpperCase(f.getName().charAt(0))+f.getName().substring(1);
                try {
                    Method m = clazz.getDeclaredMethod(setMethodName,f.getType());
                    if(needDes){
                        v = DES.decrypt((String) v);
                    }
                    m.invoke(bean,v);
                } catch (Exception e) {
                    actionResult.add(String.format("[%s]的值输入有错，请输入正确的类型！",displayName));
                }
            }
        }
        return bean;
    }

    private static Object parseBeanValue(Field f,String parameterValue,String displayName,ActionResult ar) {
        Object v = null;
        try {
            if(f.getType().equals(Date.class)){
                String dateFormat = "yyyy-MM-dd";
                String[] arr = parameterValue.split(":");
                if(arr.length == 1){
                    //再检测一下有没有小时
                    arr = parameterValue.split("\\s");
                    if(arr.length == 2){
                        //仅有小时，没有分及秒
                        dateFormat += " HH";
                    }
                }else if(arr.length == 2){
                    //有小时，有分，但没有秒
                    dateFormat += " HH:mm";
                }else if(arr.length == 3){
                    //有小时，有分，也有秒
                    dateFormat += " HH:mm:ss";
                }
                v = DateUtils.toDate(parameterValue, dateFormat);
            }else if(f.getType().equals(Time.class)){
                if(StringUtils.isNotEmpty(parameterValue)){
                    String[] arr = parameterValue.split(":");
                    String vv = parameterValue;
                    if(arr.length == 2){
                        vv += ":00";
                    }
                    v = Time.valueOf(vv);
                }
            }else{
                v = org.apache.commons.beanutils.ConvertUtils.convert(parameterValue, f.getType());
            }
        }catch (Exception e){
            ar.add(String.format("[%s]的值输入有错，请输入正确的类型！",displayName));
        }
        return v;
    }

    public LoginUser getUser(){
        LoginUser user = (LoginUser) WebUtils.getSessionAttribute(request, LoginUser.SESSION_KEY);
        if(null == user){
            throw new ApplicationException("您已长时间没有操作,为安全起见,系统将自动退出");
        }
        return user;
    }

    public void toExcel(String s,String fileName)throws IOException{
        response.setCharacterEncoding(DEFAULT_CHARSET);
        response.setContentType("application/vnd.ms-excel;charset=utf8");
        response.addHeader("Content-Disposition", "inline;filename=" + fileName);
        PrintWriter out = response.getWriter();
        out.print(s);
        out.flush();
    }
}
